//
// AgentExploringCell class - One cell as how is seen by the agent
//
package classes;

public class AgentExploringCell {
	
  private int x;
  private int y;
  private AgentExploringWorld world;
  
	public AgentExploringCell (AgentExploringWorld w, int x, int y) {
	  this.x = x;
	  this.y = y;
	  this.world = w;
	  
		isDiscovered = false;
		isVisited = false;

	  percept = new int [3];
	  objectProb = new float [3];
	  isSure = new boolean [3];
	  
	  for (int i=0; i<3; i++) {
	    percept[i]=0;
	    objectProb[i]=0;
	    isSure[i]=false;
	  }
	}
	
	// know some info about cell, false by default; comes true, when it's one of adjustments cells of agent
	boolean isDiscovered;
	
	// if agent has visited this cell, false by default; comes true if agent steps on it
	boolean isVisited;
	
	// indicates how many percepts the cell has
	int [] percept;
	
	// this is what agent thinks of feeling the cell according to percepts and logic, in percents
	// probabilities of feelings in current cell
	float   [] objectProb;
	boolean [] isSure;
	boolean  isBat;
	boolean  isExit;
	
	private void updateProbs(int nPercept, boolean add) {
    int notSureCells = 0;
	  
    isSure[nPercept] = true;

    // update surrounding probabilities
    AgentExploringCell [] cellsAround = world.arrayOfCellsAround(world.agentWorld[x][y]);
    for (int i=0; i<4; i++) {
      // the number of percepts for that type are not needed because this information
      // is in the probabilities, as we are distributing them to the other cells around
      if (cellsAround[i].percept[nPercept]>0) {
        AgentExploringCell [] cProb = world.arrayOfCellsAround(cellsAround[i]);
        for (int j=0; j<4; j++) if (!cProb[j].isSure[nPercept]) notSureCells++;
        for (int j=0; j<4; j++)
          if (!cProb[j].isSure[nPercept]) {
            if (add) cProb[j].objectProb[nPercept]-=objectProb[nPercept];
            else     cProb[j].objectProb[nPercept]+=(objectProb[nPercept]/notSureCells);
            // may have to be update recursively in case of pits?
            if (objectProb[nPercept]==1 || objectProb[nPercept]==0) cProb[j].isSure[nPercept] = true;
          }
      }
    }

    objectProb[nPercept] = add ? 1 : 0;
	}
	
  public void putPit() {
    // we don't set the wampus probability to 0, as pit & wampus can be in the same cell
    updateProbs(0, true);
    updateProbs(2, false);
    isBat = false;
    isExit = false;
  }
  
  public void putWampus() {
    // we don't set the pit probability to 0, as pit & wampus can be in the same cell
    updateProbs(1, true);
    updateProbs(2, false);
    isBat = false;
    isExit = false;
  }
  
  public void putGold() {
    updateProbs(0, false);
    updateProbs(1, false);
    updateProbs(2, true);
    isBat = false;
    isExit = false;
  }
  
  public void putBat() {
    updateProbs(0, false);
    updateProbs(1, false);
    updateProbs(2, false);
    isBat = true;
    isExit = false;
  }
  
  public void putExit() {
    updateProbs(0, false);
    updateProbs(1, false);
    updateProbs(2, false);
    isBat = false;
    isExit = true;
  }
   
  public void putNothing() {
    updateProbs(0, false);
    updateProbs(1, false);
    updateProbs(2, false);
    isBat = false;
    isExit = false;
  }
  
  public int getX() {
    return x;
  }
  
  public int getY() {
    return y;
  }
}
